/* $RCSFile: LangChooser.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.Core/UI/WebControls/LangChooser.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:30  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.Collections;
using System.Globalization;
using System.Reflection;
using System.Configuration;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.UI.Design;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Security.Permissions;

using AddonNice.Diagnostics;
using AddonNice.Settings;
using AddonNice.Configuration;
using AddonNice.Helpers;
using Telerik.Web.UI;

using Trace2    =   System.Diagnostics.Trace;

namespace AddonNice.UI.WebControls
{

 	#region Local TraceSwitch 
	public class LangChooserTrace : ADNTraceSwitch
	{
		static public ADNTraceSwitch	Sw	=	new ADNTraceSwitch("LangChooserTrace","Special Trace Switch for LangChooser");
	}
	#endregion Local TraceSwitch 

    /// <summary>
	/// This class contains 2 fontionnalities: 
    /// - a static implementation to select current portal language from various sources: viewstate, querystring,cookie,default portal settings
    /// - a webControl to change current browser language 
	/// </summary>
	[ToolboxData("<{0}:LangChooser runat='server'></{0}:LangChooser>")]
	[Designer("AddonNice.UI.Design.LangChooserDesigner")]
	[DefaultProperty("LanguageListString")]
	public class LangChooser : WebControl 
	{
		public const string SWITCHER_COOKIE_PREFIX  =   "ADNCRM_Lang_"; 

        const string langStr                        =   "lang";
        const string adn_LangSw_ddStr               =   "adn_LangSw_dd";
        const string adncrm_Lang_CurrentUICultureStr=   "adncrm_Lang_CurrentUICulture";
        const string adncrm_Lang_CurrentCultureStr  =   "adncrm_Lang_CurrentCulture";
        const string NoLangChooserStr               =   "[E]LangChooser InternalGetViewState no LangChooser";
        const string NoLangChooser2Str              =   "[E]LangChooser InternalSetViewState no LangChooser";
        const string NoViewStateValueStr            =   "[V]LangChooser InternalGetViewState no values in ViewState";
        const string OnChangeLanguageNoPortal       =   "[E]LangChooser OnChangeLanguage PortalSettings Not defined";

        const string adn_LangSw_selStr              =   "adn_LangSw_sel";
        const string adn_LangSw_tblStr              =   "adn_LangSw_tbl";

		private RadComboBox langDropDown            =   null;

		#region Properties
		
        /// <summary>
		/// Normally the Language part is shown as Native name (the name in the proper language).
		/// Set ShowNative to false for showing names in english.
		/// </summary>
		[DefaultValue(LangChooserName.NativeName)]
		public LangChooserName ShowNameAs
		{
			get
			{
				if (ViewState["ShowNameAs"] != null)
					return (LangChooserName) ViewState["ShowNameAs"]; 
				return LangChooserName.NativeName;
			}
			set
			{
				ViewState["ShowNameAs"] = value;
				ChildControlsCreated = false;
			}
		}

		/// <summary>
		/// Should we display labels, default true
		/// </summary>
		[DefaultValue(true)]
		public bool DisplayLabels
		{
			get
			{
				if (ViewState["DisplayLabels"] != null)
					return (bool) ViewState["DisplayLabels"];
				return true;
			}
			set
			{
				ViewState["DisplayLabels"]  =   value;
				ChildControlsCreated        =   false;
			}
		}

		/// <summary>
		/// Should we include we include LangChooser automatically in AjaxManager
		/// </summary>
		[DefaultValue(true)]
		public bool AutoCallBack
		{
			get
			{
				if (ViewState["AutoCallBack"] != null)
					return (bool) ViewState["AutoCallBack"];
				return true;
			}
			set
			{
				ViewState["AutoCallBack"]     =   value;
			}
		}

		/// <summary>
		/// Normally the Language part is shown (UI).
		/// Choose DisplayCultureList to show the Culture part.
		/// </summary>
		[DefaultValue(LangChooserFlagType.DisplayUICultureList)]
		public LangChooserFlagType Labels
		{
			get
			{
				if (ViewState["Labels"] != null)
					return (LangChooserFlagType) ViewState["Labels"];
				return LangChooserFlagType.DisplayUICultureList;
			}
			set
			{
				ViewState["Labels"]     =   value;
				ChildControlsCreated    =   false;
			}
		}
		
		/// <summary>
		/// How do we display flags
		/// Choose DisplayNone for hide Flags.
		/// Choose DisplayOutSide for flags in a cell before Combo selection.
		/// Choose DisplayInside for flags inside each combo item.
        /// Could mix choices with DisplayOutSide|DisplayInside
		/// </summary>
		[DefaultValue(LangChooserDisplay.DisplayOutSide)]
		public LangChooserDisplay Flags
		{
			get
			{
				if (ViewState["Flags"] != null)
					return ((LangChooserDisplay) ViewState["Flags"]); 
				return LangChooserDisplay.DisplayOutSide;
			}
			set
			{
				ViewState["Flags"]      =   value;
				ChildControlsCreated    =   false;
			}
		}

		/// <summary>
		/// Choose DisplayCultureList to show the Culture part.
		/// Choose DisplayUICultureList to show the Culture part.
		/// </summary>
		[DefaultValue(LangChooserFlagType.DisplayCultureList)]
		public LangChooserFlagType FlagType
		{
			get
			{
				if (ViewState["FlagType"] != null)
					return ((LangChooserFlagType) ViewState["FlagType"]); 
				return LangChooserFlagType.DisplayCultureList;
			}
			set
			{
				ViewState["FlagType"]   =   value;
				ChildControlsCreated    =   false;
			}
		}
    
        /// <summary>
		/// LangChooser Type
		/// </summary>
		[DefaultValue(LangChooserType.DropDownList)]
		public LangChooserType Type
		{
			get
			{
				if (ViewState["LangType"] != null)
					return (LangChooserType) ViewState["LangType"]; 
				return LangChooserType.DropDownList;
			}
			set
			{
				ViewState["LangType"]   = value;
				ChildControlsCreated    = false;
			}
		}
		
		/// <summary>
		/// Image path
		/// </summary>
		[DefaultValue("~/aspnet_client/flags/")]
		public string ImagePath
		{
			get
			{
				string imagePath = ((string) ViewState["ImagePath"]);
				if (imagePath != null)
					return imagePath; 
                if ( !DesignMode )
    				return Path.ToAbsolute(Config.PortalFlagsPath); //point to aspnet
                return "/aspnet_client/flags/";
			}
			set
			{
				ViewState["ImagePath"] = value;
			}
		}

		/// <summary>
		/// Url where redirecting language changes.
		/// An empty walue reload current page.
		/// </summary>
		[DefaultValue("")]
		public string ChangeLanguageUrl
		{
			get
			{
				string _changeLanguageUrl = ((string) ViewState["ChangeLanguageUrl"]);
				if (_changeLanguageUrl != null)
					return _changeLanguageUrl; 
				return string.Empty;
			}
			set
			{
				ViewState["ChangeLanguageUrl"] = RemoveQueryString(value,langStr);
			}
		}

		/// <summary>
		/// Choose how language switcher change language when using the dropdown/radcombo.
		/// In LangChooserAction.LinkRedirect mode a redirect is automatially performed by selectedIndexChange handler
		/// Else a handler is called if installed
		/// </summary>
		[DefaultValue(LangChooserAction.LinkRedirect)]
		public LangChooserAction ChangeLanguageAction
		{
			get
			{
				if (ViewState["ChangeLanguageAction"] != null)
					return (LangChooserAction) ViewState["ChangeLanguageAction"]; 
				return LangChooserAction.LinkRedirect;
			}
			set
			{
				ViewState["ChangeLanguageAction"] = value;
			}
		}
        
		private LanguageCultureCollection LanguageList
		{
			get
			{
				return (LanguageCultureCollection) LanguageListString;
			}
		}
		[DefaultValue("en=en-US")]
		[PersistenceMode(PersistenceMode.Attribute)]
		public string LanguageListString
		{
			get
			{
				if (ViewState["LanguageList"] != null)
					return (string) ViewState["LanguageList"];
                if ( !DesignMode )
				    return PortalModuleControl.GetLanguageCultureList().ToString();
                return "en=en-US";
			}
			set
			{
                ViewState["LanguageList"] = (string) value;
				ChildControlsCreated = false;
			}
		}

        int _CellPadding                     =   3;
        public int CellPadding
		{
			get
			{
				return _CellPadding;
			}
			set
			{
                _CellPadding    =   value;
            }
		}

        int _CellSpacing                     =   0;
        public int CellSpacing
		{
			get
			{
				return _CellSpacing;
			}
			set
			{
                _CellSpacing    =   value;
            }
		}
        
        Unit _ComboWidth                    =   Unit.Empty;
        public Unit ComboWidth                    
		{
			get
			{
				return _ComboWidth;
			}
			set
			{
                _ComboWidth    =   value;
            }
		}

        static PortalSettings portalSettings
        {
            get
            {
                PortalSettings ps = (PortalSettings)HttpContext.Current.Items[StStr.strPortalSettings];

                if (ps == null)
                {
                    if (LangChooserTrace.Sw.TraceError)
                        Trace2.WriteLine(OnChangeLanguageNoPortal, LangChooserTrace.Sw.Info);
                    throw (new Exception(OnChangeLanguageNoPortal));
                }
                return ps;
            }
        }

		#endregion Properties

        #region Ctor
		
        public LangChooser()
		{
			if (Context == null || Context.Request == null)
                return;
		    ChangeLanguageUrl = Context.Request.RawUrl;
  			if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser Ctor ChangeLanguageUrl: {0}",ChangeLanguageUrl),LangChooserTrace.Sw.Info);
		}
		#endregion

		#region Control creation

        protected override void RenderContents(HtmlTextWriter output)
		{
			EnsureChildControls();
			foreach (Control ctrl in Controls)
				ctrl.RenderControl(output);
		}

        /// <summary>
		/// Override CreateChildControls to create a  Table with one or two columns
		/// </summary>
		protected override void CreateChildControls() 
		{
			if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser CreateChildControls BEG Type: {0}",Type),LangChooserTrace.Sw.Info);
			
            if ( !DesignMode )
                ProcessCultures(LanguageListString,portalSettings.BaseAlias, this);

			Controls.Clear();
			Table myTable                               =   new Table();
			myTable.CellPadding                         =   CellPadding;
			myTable.CellSpacing                         =   CellSpacing;
            if ( (Width == null ) || ( Width == Unit.Empty ) )
                    myTable.Style.Add(HtmlTextWriterStyle.Width,"100%");
            else    myTable.Style.Add(HtmlTextWriterStyle.Width,Width.ToString(CultureInfo.InvariantCulture));
			TableRowCollection myRows                   =   myTable.Rows;

            LanguageCultureItem myCurrentLanguage       =   GetCurrentLanguage();
            string myCurrentLanguageUICulture           =   myCurrentLanguage.UICulture.ToString();
            bool DisplayExternalFlag                    =   ( (Flags & LangChooserDisplay.DisplayOutSide) == LangChooserDisplay.DisplayOutSide);
            bool DisplayInternalFlag                    =   ( (Flags & LangChooserDisplay.DisplayInside) == LangChooserDisplay.DisplayInside);
			switch (Type)
			{
				//Drop down list
				case LangChooserType.DropDownList:

					TableRow myTableRowDD               =   new TableRow();
					if ( DisplayExternalFlag )
					{
						Image myImage                   =   new Image();
						myImage.ImageUrl                =   GetFlagImg(myCurrentLanguage);
						TableCell myTableCellFlag       =   new TableCell();
				        myTableCellFlag.CssClass        =   adn_LangSw_selStr;
						myTableCellFlag.Controls.Add(myImage);
						myTableRowDD.Controls.Add(myTableCellFlag);
					}

					TableCell myTableCellDropDown       =   new TableCell();
					if ( DisplayExternalFlag  )
				        myTableCellDropDown.CssClass    =   adn_LangSw_tblStr;
					langDropDown                        =   new RadComboBox();
					langDropDown.ID                     =   ID+adn_LangSw_ddStr;
                    langDropDown.Width                  =   ComboWidth;
                    langDropDown.AutoPostBack           =   true;
					foreach(LanguageCultureItem i in LanguageList)
					{
			            RadComboBoxItem lstItem         =   new RadComboBoxItem(GetName(i), i.UICulture.Name);
                        // insert the image
					    if ( DisplayInternalFlag )
                            lstItem.ImageUrl            =   GetFlagImg(i);
			            if ( LangChooserTrace.Sw.TraceVerbose )
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser CreateChildControls Adding: {0}-{1}",lstItem.Text,lstItem.Value),LangChooserTrace.Sw.Info);
						langDropDown.Items.Add(lstItem);
						if (i.UICulture.ToString() == myCurrentLanguageUICulture ) //Select current language
							lstItem.Selected            =   true;
					}
					
					myTableCellDropDown.Controls.Add(langDropDown);
					myTableRowDD.Controls.Add(myTableCellDropDown);
					myRows.Add(myTableRowDD);
					break;

					// Links
				case LangChooserType.VerticalLinksList:

					foreach (LanguageCultureItem l in LanguageList)
					{
						TableRow myTableRowLinks        =   new TableRow();
						if ( DisplayExternalFlag )
							myTableRowLinks.Controls.Add(GetFlagCell(l));
						if ( DisplayLabels )
							myTableRowLinks.Controls.Add(GetLabelCell(l));
						myRows.Add(myTableRowLinks);
					}
					break;

					// Horizontal links
				case LangChooserType.HorizontalLinksList:

					TableRow myTableRowLinksHorizontal  =    new TableRow();
					
					foreach (LanguageCultureItem l in LanguageList)
					{
						if ( DisplayExternalFlag )
							myTableRowLinksHorizontal.Controls.Add(GetFlagCell(l));
						if ( DisplayLabels )
							myTableRowLinksHorizontal.Controls.Add(GetLabelCell(l));
					}
					myRows.Add(myTableRowLinksHorizontal);
					break;
			}

			Controls.Add(myTable);
            ChildControlsCreated                        =   true;
		}

        /// <summary>
        /// If LangChooserType.DropDownList add handler for selectedIndex change on RadCombobox
        /// </summary>
        protected override void OnInit(EventArgs e)
        {
			if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser OnInit BEG Type: {0}",Type),LangChooserTrace.Sw.Info);
            EnsureChildControls();
            Load                    +=  new EventHandler(LangChooser_Load);
            if ( langDropDown != null )
                langDropDown.SelectedIndexChanged += new RadComboBoxSelectedIndexChangedEventHandler(langDropDown_SelectedIndexChanged);
            base.OnInit(e);
			if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine("[V]LangChooser OnInit END.",LangChooserTrace.Sw.Info);
        }

        /// <summary>
        /// If LangChooserType.DropDownList add to AjaxManager if exists
        /// </summary>
        void LangChooser_Load(object sender,EventArgs e)
        {
			if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser LangChooser_Load BEG Type: {0}, Page.IsPostBack: {1}, Page.IsCallback: {2}.",
                    Type,Page.IsPostBack,Page.IsCallback),LangChooserTrace.Sw.Info);
            if ( AutoCallBack && ( Type ==  LangChooserType.DropDownList ) && ( Page is ADNPage ))
            {
                if ( ((ADNPage)Page).HasAjaxManager )
                    ((ADNPage)Page).AddAjaxSetting(this,this);
            }
            if ( !Page.IsPostBack && !Page.IsCallback )
            {
                if ( string.IsNullOrEmpty(LanguageListString) )
                    LanguageListString =    PortalModuleControl.GetLanguageCultureList().ToString();
            }
			if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser LangChooser_Load END Type: {0}",Type),LangChooserTrace.Sw.Info);
        }


		#endregion

		#region Events and delegates
		
        /// <summary>
		/// Local : Could send a redirect, so not all handlers are garanteed to fire
		/// </summary>
		public event LangChooserEventHandler ChangeLanguage;

        /// <summary>
		/// Static should not send a redirect, so all handlers are garanteed to fire
		/// </summary>
		public static event LangChooserEventHandler ChangeLanguageNoRedirect;
		
        
        
        /// <summary>
		/// Event Triggered when a language change has been done on client.
		/// </summary>
		protected virtual void OnStaticChangeLanguage(LangChooserEventArgs e)
		{
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser OnStaticChangeLanguage BEG CultureItem: {0}",e.CultureItem.Culture.EnglishName),LangChooserTrace.Sw.Info);
            bool HasEvents      =   (ChangeLanguageNoRedirect != null);
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser ChangeLanguageNoRedirect HasEvents: {0}.",HasEvents),LangChooserTrace.Sw.Info);
			if ( HasEvents )
				ChangeLanguageNoRedirect(this, e); //Invokes the delegates
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine("[V]LangChooser ChangeLanguageNoRedirect END.",LangChooserTrace.Sw.Info);
		}
        
        
        /// <summary>
		/// Event Triggered when a language change has been done on client.
		/// </summary>
		protected virtual void OnChangeLanguage(LangChooserEventArgs e)
		{
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser OnChangeLanguage BEG CultureItem: {0}",e.CultureItem.Culture.EnglishName),LangChooserTrace.Sw.Info);
            bool HasEvents      =   (ChangeLanguage != null);
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser OnChangeLanguage HasEvents: {0}.",HasEvents),LangChooserTrace.Sw.Info);
			if ( HasEvents )
				ChangeLanguage(this, e); //Invokes the delegates
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine("[V]LangChooser OnChangeLanguage END.",LangChooserTrace.Sw.Info);
		}

        /// <summary>
        /// Available for Radombo only, else the url is directly called
        /// </summary>
        void langDropDown_SelectedIndexChanged(object o,RadComboBoxSelectedIndexChangedEventArgs e)
        {
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser langDropDown_SelectedIndexChanged BEG ChangeLanguageAction: {0}, eventArgument: '{1}'",
                    ChangeLanguageAction,e.Value),LangChooserTrace.Sw.Info);
            // Updates current cultures: force to persist the cookie...but we do a redirect
		    LanguageCultureItem myItem = LanguageList.GetBestMatching(new CultureInfo(e.Value));
            SetCurrentLanguage(myItem, portalSettings.BaseAlias, this);
            // to avoid having portal desktoptabs in a different language as the current one
            portalSettings.ReloadPortal(false);
            OnStaticChangeLanguage(new LangChooserEventArgs(myItem));
			if ( ChangeLanguageAction == LangChooserAction.LinkRedirect )
			{
                if ( Page is ADNPage )
				        ((ADNPage)Page).Redirect(GetLangUrl(e.Value),true);
				else    Context.Response.Redirect(GetLangUrl(e.Value),true);
			}
			else
			{
                if ( LangChooserTrace.Sw.TraceVerbose )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser langDropDown_SelectedIndexChanged myItem: {0}",myItem.Culture.EnglishName),LangChooserTrace.Sw.Info);
				OnChangeLanguage(new LangChooserEventArgs(myItem));
			}
        }

		#endregion

		#region Private Implementation

		private TableCell GetFlagCell(LanguageCultureItem l)
		{
			TableCell myTableCellFlag           =   new TableCell();
			if (l.UICulture.ToString() == GetCurrentLanguage().UICulture.ToString())
				    myTableCellFlag.CssClass    =   adn_LangSw_selStr;
            else	myTableCellFlag.CssClass    =   adn_LangSw_tblStr; 

			HyperLink myImage                   =   new HyperLink();
			myImage.NavigateUrl                 =   GetLangUrl(l.UICulture.Name);
			myImage.ImageUrl                    =   GetFlagImg(l);
			myImage.Text                        =   GetName(l);
			myTableCellFlag.Controls.Add(myImage);
			return myTableCellFlag;
		}

		private TableCell GetLabelCell(LanguageCultureItem l)
		{
			TableCell myTableCellLabel          =   new TableCell();

			if (l.UICulture.ToString() == GetCurrentLanguage().UICulture.ToString())
				myTableCellLabel.CssClass       =   adn_LangSw_selStr; 
			else
				myTableCellLabel.CssClass       =   adn_LangSw_tblStr; 

			HyperLink myLabel                   =   new HyperLink();
			myLabel.NavigateUrl                 =   GetLangUrl(l.UICulture.Name);
			myLabel.Text                        =   GetName(l);
			myTableCellLabel.Controls.Add(myLabel);
					
			return myTableCellLabel;
		}

		private string GetFlagImg(LanguageCultureItem languageItem)
		{
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser GetFlagImg langItem: {0}, Flags: {1}",languageItem.UICulture.EnglishName,Flags),LangChooserTrace.Sw.Info);
			CultureInfo myCulture;

			switch(FlagType)
			{
				case LangChooserFlagType.DisplayUICultureList:
					myCulture   =   languageItem.UICulture;
					break;

				default:
				case LangChooserFlagType.DisplayCultureList:
					myCulture   =   languageItem.Culture;
					break;
			}

			//Flag must be specific
			if (myCulture.IsNeutralCulture)
				myCulture       =   CultureInfo.CreateSpecificCulture(myCulture.Name);

			string flagImgUrl;
			if (myCulture.Name.Length > 0)
				flagImgUrl      =   string.Format("{0}flags_{1}.gif",ImagePath,myCulture.Name);
			else
				flagImgUrl      =   ImagePath + "flags_unknown.gif";

			return flagImgUrl;
		}

   		/// <summary>
		/// Remove queryNm from query string
		/// </summary>
        public string RemoveQueryString(string Url,string queryNm)
        {
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser RemoveQueryString BEG url: '{0}', queryNm: '{1}'.",Url,queryNm),LangChooserTrace.Sw.Info);
            string str          =   Url;
            int idx2            =   str.IndexOf('?');
            if (idx2 > -1)
            {
                string query    =   str.Substring(idx2+1);
                if ( LangChooserTrace.Sw.TraceVerbose )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser RemoveQueryString query: {0}, queryNm: {1}",query,queryNm),LangChooserTrace.Sw.Info);
                char[] tc       =   new char[]{'&'};
                string[] tbquery=   query.Split(tc,StringSplitOptions.RemoveEmptyEntries);
                StringBuilder sb    =   new StringBuilder(str.Substring(0,idx2+1));
                for ( int i=0 ; i < tbquery.Length ; i++ )
                {
                    string p    =   tbquery[i];
                    if ( p.IndexOf(queryNm + "=") > -1 )
                        continue;
                    sb.AppendFormat("{0}&",p);
                }
                str             =   sb.ToString().TrimEnd(tc);
                str             =   str.TrimEnd(new char[]{'?'});
                if ( LangChooserTrace.Sw.TraceVerbose )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser RemoveQueryString str: '{0}'",str),LangChooserTrace.Sw.Info);
            }
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser RemoveQueryString Url: {0}, Result: {1}",Url,str),LangChooserTrace.Sw.Info);
            return str;
        }

		/// <summary>
        /// This is the url where direct postback or redirect (DropDown) will occur 
		/// </summary>
		public string GetLangUrl(string language)
		{
            string str      =   string.Empty;
            str         =   RemoveQueryString(ChangeLanguageUrl,langStr);
            if ( str.IndexOf('?') == -1 )
                    str =   str + "?"; 
            else    str =   str + "&"; 
            str         =   str +langStr+"=" + language; 
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser GetLangUrl Url: '{0}'",str),LangChooserTrace.Sw.Info);
            return str; 
        }

        private string GetName(LanguageCultureItem languageItem)
		{
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser GetName langItem: {0}, Labels: {1}, ShowNameAs: {2}",languageItem.UICulture.EnglishName,Labels,ShowNameAs),LangChooserTrace.Sw.Info);

            CultureInfo myCulture;
            if ( ! DisplayLabels )
                return string.Empty;
			switch(Labels)
			{
				default:
				case LangChooserFlagType.DisplayUICultureList:
					myCulture   =   languageItem.UICulture;
					break;

				case LangChooserFlagType.DisplayCultureList:
					myCulture   =   languageItem.Culture;
					break;
			}

			switch(ShowNameAs)
			{
				default:
				case LangChooserName.NativeName:
					return languageItem.Culture.TextInfo.ToTitleCase(myCulture.NativeName);

				case LangChooserName.DisplayName:
					return languageItem.Culture.TextInfo.ToTitleCase(myCulture.DisplayName);

				case LangChooserName.EnglishName:
					return languageItem.Culture.TextInfo.ToTitleCase(myCulture.EnglishName);
			}
		}
		#endregion

		#region Static Implementation
		
        /// <summary>
		/// Persist language in a cookie
		/// Call SetCurrentLanguage with no cookie name and no control
		/// </summary>
		public static void SetCurrentLanguage(LanguageCultureItem langItem)
		{
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser SetCurrentLanguage langItem: {0}",langItem.UICulture.EnglishName),LangChooserTrace.Sw.Info);
			SetCurrentLanguage(langItem,string.Empty,null);
		}
		
		/// <summary>
		/// Persist language in a cookie
		/// Call SetCurrentLanguage with no control
		/// </summary>
		public static void SetCurrentLanguage(LanguageCultureItem langItem, string cookieAlias)
		{
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser SetCurrentLanguage langItem: {0}, cookieAlias: {1}",langItem.UICulture.EnglishName,cookieAlias),LangChooserTrace.Sw.Info);
			SetCurrentLanguage(langItem, cookieAlias, null);
		}

		/// <summary>
		/// Persist language in a cookie and install it in current thread culture and UICulture
		/// </summary>
		internal static void SetCurrentLanguage(LanguageCultureItem langItem, string cookieAlias, LangChooser switcher)
		{
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser SetCurrentLanguage cookieAlias: {0}, LangChooser is null: {1}, UICulture: {2}, Culture: {3}", 
                    new object[] { cookieAlias, (switcher == null), langItem.UICulture.EnglishName, langItem.Culture.EnglishName }),LangChooserTrace.Sw.Info);
			Thread.CurrentThread.CurrentUICulture   =   langItem.UICulture;
			Thread.CurrentThread.CurrentCulture     =   langItem.Culture;
			//Persists choice
            if ( switcher != null )
			    InternalSetViewState(langItem, switcher);
            if ( !string.IsNullOrEmpty(cookieAlias))
			    InternalSetCookie(langItem, cookieAlias);
		}

        /// <summary>
        /// Return the current tread CurrentUICulture and CurrentCulture as an AddonNice LanguageCultureItem
        /// </summary>
		public static LanguageCultureItem GetCurrentLanguage()
		{
			return new LanguageCultureItem(Thread.CurrentThread.CurrentUICulture, Thread.CurrentThread.CurrentCulture);
		}

		/// <summary>
		/// Get current Language from Querystring, looking for parameter 'lang'
		/// </summary>
		private static LanguageCultureItem InternalGetQuerystring(LanguageCultureCollection myLanguagesCultureList)
		{
			if ( HttpContext.Current == null )
                return null;
            string ob   =   HttpContext.Current.Request.Params[langStr];

            if ( string.IsNullOrEmpty(ob) )
            {
                if ( LangChooserTrace.Sw.TraceVerbose )
                    Trace2.WriteLine( "[V]LangChooser InternalGetQuerystring Params['lang'] is null",LangChooserTrace.Sw.Info);
                return null;
            }
			try
			{
                if ( LangChooserTrace.Sw.TraceWarning )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalGetQuerystring Lang in Request: {0}",ob),LangChooserTrace.Sw.Info);
				return myLanguagesCultureList.GetBestMatching(new CultureInfo(ob));
			}
			catch(ArgumentException ex) //Maybe an invalid CultureInfo
			{
                if ( LangChooserTrace.Sw.TraceError )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]LangChooser InternalGetQuerystring ex: {0}",ex),LangChooserTrace.Sw.Info);
				return null;
			}
		}

		/// <summary>
		/// Get current Language from User language list
		/// </summary>
		private static LanguageCultureItem InternalGetUserLanguages(LanguageCultureCollection myLanguagesCultureList)
		{
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalGetUserLanguages BEG myLanguagesCultureList.Count: {0}",myLanguagesCultureList.Count),LangChooserTrace.Sw.Info);
			//Get userLangs
			CultureInfo[] userLangs;
            if(HttpContext.Current == null )
                return null;
            LanguageCultureItem userLanguage            =   null;
			if( HttpContext.Current.Request.UserLanguages != null && HttpContext.Current.Request.UserLanguages.Length > 0)
			{
                if ( LangChooserTrace.Sw.TraceVerbose )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalGetUserLanguages HttpContext.Current.Request.UserLanguages.Length: {0}",HttpContext.Current.Request.UserLanguages.Length),LangChooserTrace.Sw.Info);
				ArrayList arrUserLangs                  =   new ArrayList(HttpContext.Current.Request.UserLanguages.Length);
                int j                                   =   0;  // copunt success
				if (HttpContext.Current.Request.UserLanguages.Length > 0)
				{
					for (Int32 i = 0; i < HttpContext.Current.Request.UserLanguages.Length  ; i++)
					{
						string currentLanguage;
						//if (arrUserLangs[i].ToString().IndexOf(';') >= 0)
                        int idx                         =   HttpContext.Current.Request.UserLanguages[i].IndexOf(';');
						if ( idx >= 0)
							currentLanguage             =   HttpContext.Current.Request.UserLanguages[i].Substring(0, idx);
						else
							currentLanguage             =   HttpContext.Current.Request.UserLanguages[i];
                        if ( LangChooserTrace.Sw.TraceVerbose )
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalGetUserLanguages currentLanguage: '{0}'",currentLanguage),LangChooserTrace.Sw.Info);
                        try
						{
							// We try the full one... if this fails we catch it
							arrUserLangs[j]             =   new CultureInfo(currentLanguage);
                            j++;
						}
						catch(ArgumentException ex)
						{
                            if ( LangChooserTrace.Sw.TraceError )
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]LangChooser InternalGetUserLanguages currentLanguage: {0}, ex: {1}",currentLanguage,ex),LangChooserTrace.Sw.Info);
							try
							{
								// Some browsers can send an invalid language
								// we try to get first two letters.. this is usually valid
                                if (currentLanguage.Length > 1)
                                {
                                    if ( LangChooserTrace.Sw.TraceVerbose )
                                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalGetUserLanguages currentLanguage substring(2): {0}", currentLanguage.Substring(2)),LangChooserTrace.Sw.Info);
                                    arrUserLangs[j]     =   new CultureInfo(currentLanguage.Substring(0,2));
                                    j++;
                                }
							}
							catch(ArgumentException ex1) // We go to next index
							{
                                if ( LangChooserTrace.Sw.TraceError )
                                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]LangChooser InternalGetUserLanguages currentLanguage: {0}, ex: {1}",currentLanguage,ex1),LangChooserTrace.Sw.Info);
							}
						}
					}
				}
                // if something Ok
                if ( j > 0 )
                {
                    userLangs                           =   (CultureInfo[])arrUserLangs.ToArray(typeof(CultureInfo));
                    // Try to match browser "accept languages" list
                    userLanguage                        =   myLanguagesCultureList.GetBestMatching(userLangs);
                }
			}
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalGetUserLanguages END Found: {0}",(userLanguage != null)),LangChooserTrace.Sw.Info);
			return userLanguage;
		}
	
		/// <summary>
		/// Get current Language from Cookie, adapt it to the 'Best Matching' culture in transmitted cultureList
		/// </summary>
		private static LanguageCultureItem InternalGetCookie(LanguageCultureCollection myLanguagesCultureList, string cookieAlias)
		{
			if (HttpContext.Current == null || cookieAlias == null )
                return null;
            string cookName                 =   SWITCHER_COOKIE_PREFIX + cookieAlias;
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalGetCookie BEG cookieAlias: '{0}'",cookName),LangChooserTrace.Sw.Info);
            LanguageCultureItem userLanguage    =   null;
            if ( HttpContext.Current.Request.Cookies[cookName] != null && HttpContext.Current.Request.Cookies[cookName].Value.Length > 0)
			{
				try
				{
                    string langStr          =   HttpContext.Current.Request.Cookies[cookName].Value;
                    if ( LangChooserTrace.Sw.TraceVerbose )
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalGetCookie lang from cookieAlias: {0}",langStr),LangChooserTrace.Sw.Info);
					userLanguage            =   myLanguagesCultureList.GetBestMatching(new CultureInfo(langStr));
				}
				catch(ArgumentException ex)
				{
					//Maybe an invalid CultureInfo
                    if ( LangChooserTrace.Sw.TraceError )
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]LangChooser InternalGetCookie cookieAlias: {0}, ex: {1}",cookieAlias,ex),LangChooserTrace.Sw.Info);
                    throw;
				}		
			}
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalGetCookie END cookieAlias: {0}, Found: {1}",cookName,(userLanguage != null)),LangChooserTrace.Sw.Info);
			return userLanguage;
		}

		/// <summary>
		/// Set current Cookie from Language
		/// </summary>
		private static void InternalSetCookie(LanguageCultureItem myLanguageCultureItem, string cookieAlias)
		{
			// Set language cookie
			if (HttpContext.Current == null || cookieAlias == null)
                return;
            string cookNm           =   SWITCHER_COOKIE_PREFIX + cookieAlias;
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalSetCookie BEG persisting lang: {0}, in cookie: {1}",myLanguageCultureItem.UICulture.Name,cookNm),LangChooserTrace.Sw.Info);
			HttpCookie langCookie   =   HttpContext.Current.Response.Cookies[cookNm];
			langCookie.Value        =   myLanguageCultureItem.UICulture.Name;
			langCookie.Path         =   "/";

			// Keep the cookie?
            if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated)
            {
                if ( LangChooserTrace.Sw.TraceVerbose )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalSetCookie persisting for 50 years lang in cookie: {0}", myLanguageCultureItem.UICulture.Name),LangChooserTrace.Sw.Info);
                langCookie.Expires  =   DateTime.Now.AddYears(50);
            }
		}

		/// <summary>
		/// Get current Language from ViewState of control sent as parameter
		/// </summary>
		private static LanguageCultureItem InternalGetViewState(LanguageCultureCollection myLanguagesCultureList, LangChooser switcher)
		{
            if (switcher == null)
            {
                if ( LangChooserTrace.Sw.TraceError )
                    Trace2.WriteLine( NoLangChooserStr,LangChooserTrace.Sw.Info);
                throw new ArgumentException(NoLangChooserStr);
            }
            if (switcher.ViewState[adncrm_Lang_CurrentUICultureStr] != null &&
                switcher.ViewState[adncrm_Lang_CurrentCultureStr] != null)
            {
                CultureInfo UICultureView       =   (CultureInfo)switcher.ViewState[adncrm_Lang_CurrentUICultureStr];
                CultureInfo CultureView         =   (CultureInfo)switcher.ViewState[adncrm_Lang_CurrentCultureStr];
                LanguageCultureItem item        =   new LanguageCultureItem(UICultureView,CultureView);
                if ( switcher != null )
                    InternalSetViewState(item,switcher);
                InternalSetCookie(item,portalSettings.BaseAlias);
                if ( LangChooserTrace.Sw.TraceVerbose )
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalGetViewState UICulture: {0}, Culture: {1}", UICultureView.EnglishName,CultureView.EnglishName),LangChooserTrace.Sw.Info);
                return item;
            }
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( NoViewStateValueStr,LangChooserTrace.Sw.Info);
			return null;
		}

		/// <summary>
		/// Set current Language in ViewState of sent control
		/// </summary>
		private static void InternalSetViewState(LanguageCultureItem myLanguageCultureItem, LangChooser switcher)
		{
            if (switcher == null)
            {
                if ( LangChooserTrace.Sw.TraceError )
                    Trace2.WriteLine( NoLangChooser2Str,LangChooserTrace.Sw.Info);
                throw new ArgumentException(NoLangChooserStr);
            }
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalSetViewState UICulture: {0}, Culture: {1}", myLanguageCultureItem.UICulture.EnglishName,myLanguageCultureItem.Culture.EnglishName),LangChooserTrace.Sw.Info);
            switcher.ViewState[adncrm_Lang_CurrentUICultureStr] = myLanguageCultureItem.UICulture;
            switcher.ViewState[adncrm_Lang_CurrentCultureStr] = myLanguageCultureItem.Culture;
		}

		/// <summary>
		/// LanguageCultureItem is first in list
		/// </summary>
		private static LanguageCultureItem InternalGetDefault(LanguageCultureCollection myLanguagesCultureList)
		{
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser InternalGetDefault UICulture: {0}", myLanguagesCultureList[0].UICulture.EnglishName),LangChooserTrace.Sw.Info);
			return myLanguagesCultureList[0];
		}

		/// <summary>
		/// Examines/combines all the variables involved and sets
		/// CurrentUICulture and CurrentCulture
		/// </summary>
		/// <param name="langList">Languages list. Something like it=it-IT;en=en-US</param>
		public static void ProcessCultures(string langList)
		{
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser ProcessCultures langList: {0}", langList),LangChooserTrace.Sw.Info);
			ProcessCultures(langList,string.Empty);
		}

		/// <summary>
		/// Examines/combines all the variables involved and sets
		/// CurrentUICulture and CurrentCulture
		/// </summary>
		/// <param name="langList">Languages list. Something like it=it-IT;en=en-US</param>
		/// <param name="cookieAlias">Alias used to make this cookie unique. Use null is you do not want cookies.</param>
		public static void ProcessCultures(string langList, string cookieAlias)
		{
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser ProcessCultures langList: {0}, cookieAlias: {1}", langList,cookieAlias),LangChooserTrace.Sw.Info);
			ProcessCultures(langList, cookieAlias, null);
		}

		/// <summary>
		/// Examines/combines all the variables involved and sets
		/// CurrentUICulture and CurrentCulture
		/// </summary>
		/// <param name="langList">Languages list. Something like it=it-IT;en=en-US</param>
		/// <param name="cookieAlias">Alias used to make this cookie unique. Use null is you do not want cookies.</param>
		/// <param name="switcher">A referenct to a Switcher control for accessing viewstate</param>
		internal static void ProcessCultures(string langList, string cookieAlias, LangChooser switcher)
		{
            if ( LangChooserTrace.Sw.TraceVerbose )
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser ProcessCultures BEG langList: {0}, cookieAlias: {1}, LangChooser is Null: {2}", langList,cookieAlias,switcher == null),LangChooserTrace.Sw.Info);
            LanguageCultureCollection myLanguagesCultureList = (LanguageCultureCollection) langList;

			//Verify that at least on language is provided
            if ( myLanguagesCultureList.Count <= 0 )
            {
                string msgStr   =   string.Format("[E]LangChooser ProcessCultures langList: {0}, cookieAlias: {1}, myLanguagesCultureList empty", langList);
                if ( LangChooserTrace.Sw.TraceError )
                    Trace2.WriteLine( msgStr,LangChooserTrace.Sw.Info);
                throw new ArgumentException(msgStr, "myLanguagesCultureList");
            }

			// Language Item
			LanguageCultureItem langItem    =   InternalGetQuerystring(myLanguagesCultureList);
            if (langItem == null)
            {
                // Viewstate
                if ( switcher != null )
                    langItem                =   InternalGetViewState(myLanguagesCultureList, switcher);
                if (langItem == null)
                {
                    // Cookie
                    langItem                =   InternalGetCookie(myLanguagesCultureList, cookieAlias);
                    if (langItem == null)
                    {
                        // UserLanguageList from browser settings
                        langItem            =   InternalGetUserLanguages(myLanguagesCultureList);
                        if (langItem == null)
                        {
                            // Default
                            langItem        =   InternalGetDefault(myLanguagesCultureList);
                        }
                    }
                }
            }
		// Updates current cultures
        if ( LangChooserTrace.Sw.TraceVerbose )
            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]LangChooser ProcessCultures langList: {0}, cookieAlias: {1}, langItem is Null: {2}", langList,cookieAlias,langItem == null),LangChooserTrace.Sw.Info);
        if (langItem != null)
		    SetCurrentLanguage(langItem, cookieAlias,switcher);
        if ( LangChooserTrace.Sw.TraceVerbose )
            Trace2.WriteLine( "[V]LangChooser ProcessCultures END.",LangChooserTrace.Sw.Info);
		}

        #endregion
	}
}
